package com.swsc.solarverse.service.schedule;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.swsc.solarverse.common.config.ResParams;
import com.swsc.solarverse.common.util.LocalDateTimeUtils;
import com.swsc.solarverse.dao.entity.analysis.StringEfficiencyRecordDO;
import com.swsc.solarverse.dao.entity.forward.ForwardStringLeDiagnoseRecordDO;
import com.swsc.solarverse.dao.entity.forward.ForwardSubmatrixLeRecordDO;
import com.swsc.solarverse.service.analysis.IStringEfficiencyRecordService;
import com.swsc.solarverse.service.forward.IForwardStringLeDiagnoseRecordService;
import com.swsc.solarverse.service.forward.IForwardSubmatrixLeRecordService;
import org.apache.commons.collections4.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author chencl
 * @Date 2024/7/6 12:07
 * @Version 1.0
 * @Description 组串IU分析
 */
@lombok.extern.slf4j.Slf4j
@org.springframework.stereotype.Service
public class StringIuAnalysisScheduleTaskService {

    private final IForwardStringLeDiagnoseRecordService forwardStringLeDiagnoseRecordService;
    private final IStringEfficiencyRecordService stringEfficiencyRecordService;
    private final IForwardSubmatrixLeRecordService forwardSubmatrixLeRecordService;

    public StringIuAnalysisScheduleTaskService(IForwardStringLeDiagnoseRecordService forwardStringLeDiagnoseRecordService,
                                               IStringEfficiencyRecordService stringEfficiencyRecordService,
                                               IForwardSubmatrixLeRecordService forwardSubmatrixLeRecordService) {
        this.forwardStringLeDiagnoseRecordService = forwardStringLeDiagnoseRecordService;
        this.stringEfficiencyRecordService = stringEfficiencyRecordService;
        this.forwardSubmatrixLeRecordService = forwardSubmatrixLeRecordService;
    }

    @org.springframework.scheduling.annotation.Async
    public void analysisSubmatrix(Integer tenantNo, Integer organNo, LocalDateTime diagnoseTime, LocalDateTime now) {
        QueryWrapper<ForwardStringLeDiagnoseRecordDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ForwardStringLeDiagnoseRecordDO::getTenantNo, tenantNo)
                .eq(ForwardStringLeDiagnoseRecordDO::getOrganNo, organNo)
                .eq(ForwardStringLeDiagnoseRecordDO::getDiagnoseTime, diagnoseTime);
        List<ForwardStringLeDiagnoseRecordDO> leDiagnoseRecordDos = forwardStringLeDiagnoseRecordService.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(leDiagnoseRecordDos)) {
            Set<String> submatrixSet = leDiagnoseRecordDos.stream().map(ForwardStringLeDiagnoseRecordDO::getSubmatrix).collect(Collectors.toSet());
            List<StringEfficiencyRecordDO> efficiencyRecordDos = stringEfficiencyRecordService.list(Wrappers.lambdaQuery(StringEfficiencyRecordDO.class)
                    .eq(StringEfficiencyRecordDO::getTenantNo, tenantNo)
                    .eq(StringEfficiencyRecordDO::getOrganNo, organNo)
                    .in(StringEfficiencyRecordDO::getSubmatrix, submatrixSet)
                    // 大于0的
                    .gt(StringEfficiencyRecordDO::getLossE, 0)
                    .ge(StringEfficiencyRecordDO::getDataTime, LocalDateTimeUtils.getDayStart(now.minusDays(1L)))
                    .lt(StringEfficiencyRecordDO::getDataTime, LocalDateTimeUtils.getDayEnd(now.minusDays(1L)))
            );
            List<ForwardSubmatrixLeRecordDO> results = new ArrayList<>(submatrixSet.size());
            for (String submatrix : submatrixSet) {
                ForwardSubmatrixLeRecordDO submatrixLeRecordDo = new ForwardSubmatrixLeRecordDO(tenantNo, organNo, submatrix, submatrix,
                        submatrix, diagnoseTime, now);
                List<ForwardStringLeDiagnoseRecordDO> subLeDiagnoseRecordDos = leDiagnoseRecordDos.stream().filter(rd -> Objects.equals(submatrix, rd.getSubmatrix())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(subLeDiagnoseRecordDos)) {
                    submatrixLeRecordDo.setAvgI(subLeDiagnoseRecordDos.get(0).getSubmatrixAvgI());
                    submatrixLeRecordDo.setAvgU(subLeDiagnoseRecordDos.get(0).getSubmatrixAvgU());
                    submatrixLeRecordDo.setSubmatrixStringNum(subLeDiagnoseRecordDos.get(0).getSubmatrixStringNum());
                    Double lossI = subLeDiagnoseRecordDos.stream().filter(drd -> null != drd.getLossI()).mapToDouble(ForwardStringLeDiagnoseRecordDO::getLossI).average().orElse(0);
                    submatrixLeRecordDo.setLossI(lossI);
                    Double lossU = subLeDiagnoseRecordDos.stream().filter(drd -> null != drd.getLossU()).mapToDouble(ForwardStringLeDiagnoseRecordDO::getLossU).average().orElse(0);
                    submatrixLeRecordDo.setLossU(lossU);
                    Double lossP = subLeDiagnoseRecordDos.stream().filter(drd -> null != drd.getLossP()).mapToDouble(ForwardStringLeDiagnoseRecordDO::getLossP).average().orElse(0);
                    submatrixLeRecordDo.setLossP(lossP);
                    // 电量损失
                    if (CollectionUtils.isNotEmpty(efficiencyRecordDos)) {
                        List<StringEfficiencyRecordDO> subEfficiencyRecordDos = efficiencyRecordDos.stream().filter(erd -> Objects.equals(submatrix, erd.getSubmatrix())).collect(Collectors.toList());
                        if (CollectionUtils.isNotEmpty(subEfficiencyRecordDos)) {
                            Double lossE = subEfficiencyRecordDos.stream().filter(erd -> null != erd.getLossE()).mapToDouble(StringEfficiencyRecordDO::getLossE).sum();
                            Integer submatrixStringNum = subEfficiencyRecordDos.get(0).getSubmatrixStringNum();
                            if (null != lossE && null != submatrixStringNum) {
                                lossE = lossE / submatrixStringNum;
                            } else {
                                lossE = subEfficiencyRecordDos.stream().filter(erd -> null != erd.getLossE()).mapToDouble(StringEfficiencyRecordDO::getLossE).average().orElse(0);
                            }
                            submatrixLeRecordDo.setLossE(lossE);
                        }
                    }
                    // 低效电流
                    List<ForwardStringLeDiagnoseRecordDO> subDiagnoseRecordDos = subLeDiagnoseRecordDos.stream().filter(drd -> Objects.equals(submatrix, drd.getSubmatrix()) &&
                            (null != drd.getLowI() && drd.getLowI() > ResParams.analysisStrLeDiagnoseLowIThreshold) &&
                            (null == drd.getLowU() || drd.getLowU() <= ResParams.analysisStrLeDiagnoseLowUThreshold)
                    ).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(subDiagnoseRecordDos)) {
                        submatrixLeRecordDo.setLowINum(subDiagnoseRecordDos.size());
                    }
                    // 低效电压
                    subDiagnoseRecordDos = subLeDiagnoseRecordDos.stream().filter(drd -> Objects.equals(submatrix, drd.getSubmatrix()) &&
                            (null != drd.getLowU() && drd.getLowU() > ResParams.analysisStrLeDiagnoseLowUThreshold) &&
                            (null == drd.getLowI() || drd.getLowI() <= ResParams.analysisStrLeDiagnoseLowUThreshold)
                    ).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(subDiagnoseRecordDos)) {
                        submatrixLeRecordDo.setLowUNum(subDiagnoseRecordDos.size());
                    }
                    // 低效电流电压
                    subDiagnoseRecordDos = subLeDiagnoseRecordDos.stream().filter(drd -> Objects.equals(submatrix, drd.getSubmatrix()) &&
                            (null != drd.getLowU() && drd.getLowU() > ResParams.analysisStrLeDiagnoseLowUThreshold) &&
                            (null != drd.getLowI() && drd.getLowI() > ResParams.analysisStrLeDiagnoseLowIThreshold)
                    ).collect(Collectors.toList());
                    if (CollectionUtils.isNotEmpty(subDiagnoseRecordDos)) {
                        submatrixLeRecordDo.setLowIUNum(subDiagnoseRecordDos.size());
                    }
                }
                results.add(submatrixLeRecordDo);
            }
            if (CollectionUtils.isNotEmpty(results)) {
                results.sort(Comparator.comparing(ForwardSubmatrixLeRecordDO::getSubmatrix));
                forwardSubmatrixLeRecordService.insertIgnoreBatch(results);
            }
        }
    }

}
